<template>
  <van-form>
    <!-- <van-button
      type="primary"
      @click="elementFind"
    >
      表单元素check
    </van-button> -->
    <!-- <van-button
      type="info"
      @click="verification"
    >
      表单验证
    </van-button> -->
    <!-- <van-button
      type="danger"
      @click="collectInfo"
    >
      信息收集
    </van-button> -->
    <!-- {{ formComponent.length }} -->
    <section
      v-for="({ component, prop }, index) in formComponent"
      :key="index"
      class="component"
    >
      <!-- {{ index + 1 }} -->
      <component
        :is="component"
        ref="fieldComp"
        v-model="prop.value"
        v-bind="prop"
        @action="triggerEvent('action')"
      />
    </section>
  </van-form>
</template>

<script>
import _ from 'lodash'
import generatorForm from '@/components/Form/mixins/generator'

export default {
  name: 'VanFormGenerator',

  mixins: [generatorForm],

  data () {
    return {
      // 表单
      formComponent: [],
    }
  },

  computed: {
    fieldComp () {
      return this.$refs.fieldComp
    },

    // 元素查找
    components () {
      let elements = []
      _.forEach(this.fieldComp, (o) => {
        elements.push(o.getElements())
      })
      elements = _.flattenDeep(elements)
      return elements
    },

    // 信息收集
    collectInfo () {
      const collectMap = []
      this.$_.forEach(this.fieldComp, ({ collectInfo = {} }) => {
        collectMap.push(collectInfo)
      })
      this.triggerEvent('collectInfo')

      // 一维数组
      const temp = this.$_
        .flattenDeep(collectMap)

      return this.$_
        .filter(temp, (o) => (o !== null))
    },
  },

  watch: {
    'formGenerator.generator': {
      handler () {
        this.formComponent = []
        this.$nextTick(() => {
          this.generator()
        })
      },
      immediate: true,
    },
  },

  methods: {
    // 获取元素属性
    getElementAttribute (attr) {
      return this.$_.map(this.fieldComp, (o) => o[attr] && o[attr])
    },

    // 表单验证
    validate () {
      // test
      // 1、获取组件实例
      // 2、validate 执行
      // 3、promise.error 马上停止执行

      const elements = this.getElements()
      const validateMap = []

      // 数组拍平
      // function deepValidate(fieldComp) {
      //   _.forEach(fieldComp, (o) => {
      //     const val = o();
      //     if (val.constructor === Array) {
      //       deepValidate(val);
      //     } else {
      //       validateMap.push(val);
      //     }
      //   });
      // }
      // deepValidate(this.getElementAttribute('validate'));
      _.forEach(elements, ({ validate }) => {
        if (validate) {
          validateMap.push(validate())
        }
      })
      // elementFind

      return new Promise((resolve, reject) => {
        Promise.all(validateMap)
          .then((data) => resolve(data))
          .catch((err) => reject(err))
          .finally(() => this.triggerEvent('validate'))
      })
    },

    // 表单校验
    verification () {
      this.validate()
    },

    // elements
    getElements () {
      const { fieldComp } = this.$refs
      let elements = []
      _.forEach(fieldComp, (o) => {
        elements.push(o.getElements())
      })
      elements = _.flattenDeep(elements)
      return elements
    },

    // 表单生成
    generator () {
      this.$emit('beforeGenerator')

      const { generator } = this.formGenerator

      this.generatorComp(generator)

      this.$nextTick(() => {
        this.triggerEvent('generator')
      })
    },

    // 事件触发
    triggerEvent (evt, val) {
      this.$emit(evt, val)

      setTimeout(() => {
        this.$emit('action')
      }, 500)
    },
  },
}
</script>
